﻿#include "InstanceScence.h"

#include "Camera.h"
#include "InstanceMesh.h"
#include "Mesh.h"
#include "Render.h"

void FInstanceScence::Init(FRender* InRender)
{
	FScence::Init(InRender);

	Camera = CreateDefaultCamera();

	PlanetModel = std::make_shared<FMeshModel>();
	PlanetModel->CustomCreateMaterialCall = [](FMeshModel::ETextureType Type)-> std::shared_ptr<FMaterial>
	{
		return std::make_shared<FMeshSimpleMaterial>();
	};

	PlanetModel->Load(FPath::BuildAssetsPath("planet"), "planet.obj");

	RockModel = std::make_shared<FInstanceModel>();
	RockModel->Load(FPath::BuildAssetsPath("rock"), "rock.obj");

	constexpr int32_t Amount = 10000;
	std::vector<glm::mat4> ModelMatrices;
	ModelMatrices.resize(Amount);

	srand(static_cast<unsigned int>(glfwGetTime())); // 初始化随机种子    
	constexpr float Radius = 50.0;
	constexpr float Offset = 2.5f;
	for (unsigned int i = 0; i < Amount; i++)
	{
		auto model = glm::mat4(1.f);
		// 1. 位移：分布在半径为 'radius' 的圆形上，偏移的范围是 [-offset, offset]
		const float Angle = static_cast<float>(i) / static_cast<float>(Amount) * 360.0f;
		float Displacement = (rand() % static_cast<int>(2 * Offset * 100)) / 100.0f - Offset;
		const float X = sin(Angle) * Radius + Displacement;
		Displacement = (rand() % static_cast<int>(2 * Offset * 100)) / 100.0f - Offset;
		const float Y = Displacement * 0.4f; // 让行星带的高度比x和z的宽度要小
		Displacement = (rand() % static_cast<int>(2 * Offset * 100)) / 100.0f - Offset;
		const float Z = cos(Angle) * Radius + Displacement;
		model = translate(model, glm::vec3(X, Y, Z));

		// 2. 缩放：在 0.05 和 0.25f 之间缩放
		const float Scale = (rand() % 20) / 100.0f + 0.05f;
		model = glm::scale(model, glm::vec3(Scale));

		// 3. 旋转：绕着一个（半）随机选择的旋转轴向量进行随机的旋转
		const float rotAngle = (rand() % 360);
		model = rotate(model, rotAngle, glm::vec3(0.4f, 0.6f, 0.8f));

		// 4. 添加到矩阵的数组中
		ModelMatrices[i] = model;
	}

	RockModel->SetInstanceTranform(ModelMatrices);
}

void FInstanceScence::Destory()
{
	FScence::Destory();
}

void FInstanceScence::Draw(float DateTime)
{
	FScence::Draw(DateTime);

	auto Projection = glm::mat4(1.f);
	Projection = glm::perspective(glm::radians(Camera->GetFOV()), Render->GetAspect(), 0.1f, 1000.0f);

	FDrawArg DrawArg;
	DrawArg.DateTime = DateTime;
	DrawArg.LightArray = {};
	DrawArg.ViewMat = Camera->GetViewMat();
	DrawArg.ViewPos = Camera->GetPosition();
	DrawArg.ProjectionMat = Projection;

	auto Model = glm::mat4(1.0f);
	Model = translate(Model, glm::vec3(0.0f, -3.0f, 0.0f));
	Model = scale(Model, glm::vec3(4.0f, 4.0f, 4.0f));
	PlanetModel->SetTransform(Model);
	PlanetModel->Draw(DrawArg);

	RockModel->Draw(DrawArg);
}
